﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.IO;
using System.Xml;
using System.Xml.Linq;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace Devtm.ServiceModel.Helpers
{


    /// <summary>
    /// allows thr creation of binding object from text
    /// </summary>
    public static class BindingHelper
    {



        public static IEnumerable<ServiceEndpoint> InitializeUrls(Type type, XElement urls)
        {

            foreach (XElement xurl in urls.Elements())
            {

                if (xurl.Name.LocalName != "url")
                    throw new ArgumentException("invalid xml format " + xurl.Name.LocalName + " url node name expected");

                string adress = string.Empty;

                XAttribute attr = xurl.Attribute("mexAdress");
                if (attr != null)
                    adress = attr.Value;
                else
                    adress = xurl.Value + @"/mex";

                MetadataExchangeClientMode mode = MetadataExchangeClientMode.MetadataExchange;
                attr = xurl.Attribute("mode");
                if (attr != null)
                    mode = (MetadataExchangeClientMode)Enum.Parse(typeof(MetadataExchangeClientMode), attr.Value);

                Uri result = null;
                if (!Uri.TryCreate(adress, UriKind.RelativeOrAbsolute, out result))
                    throw new ArgumentException("invalid url " + xurl.Value);

                ServiceEndpointCollection endpoints = MetadataResolver.Resolve(type, result, mode);

                foreach (ServiceEndpoint point in endpoints)
                    if (point != null)
                        yield return point;

            }

        }


        public static IEnumerable<ServiceEndpoint> InitializeUrls(Type type, Uri adress, MetadataExchangeClientMode mode)
        {         

            ServiceEndpointCollection endpoints = MetadataResolver.Resolve(type, adress, mode);

            foreach (ServiceEndpoint point in endpoints)
                if (point != null)
                    yield return point;

        }




        public static KeyValuePair<EndpointAddress, Binding> InitializeServiceModel(XElement sectionServiceModel)
        {
            Binding binding = GetBinding(sectionServiceModel);
            EndpointAddress address = GetUri(sectionServiceModel);

            return new KeyValuePair<EndpointAddress, Binding>(address, binding);
        }



        public static Binding GetBinding(XElement x)
        {

            XElement endpoint1 = x.Element("client").Element("endpoint");
            XElement bindingContent = x.Element("bindings");
            XAttribute bindingConfiguration = endpoint1.Attribute("bindingConfiguration");

            Binding binding = BindingHelper.CreateBinding
            (
              endpoint1.Attribute("binding").Value,
              bindingConfiguration != null ? bindingConfiguration.Value : string.Empty,
              bindingContent != null ? bindingContent.ToString() : string.Empty
            );

            return binding;

        }



        public static EndpointAddress GetUri(XElement x)
        {
            XElement endpoint1 = x.Element("client").Element("endpoint");
            XAttribute add = endpoint1.Attribute("address");
            EndpointAddress address = new EndpointAddress(add.Value);
            return address;
        }      




        /// <summary>
        /// Configures the binding for the selected endpoint
        /// </summary>
        /// <param name="bindingName"></param>
        /// <param name="group"></param>
        /// <returns></returns>
        public static Binding CreateBinding(string bindingName, string bindingConfiguration, string bindingContent)
        {

            Binding b = null;

            // On récupère la section bindings
            BindingsSection conf = System.Configuration.ConfigurationManager.GetSection(@"system.serviceModel/bindings") as BindingsSection;

            // On créer un objet pour l'assignement des propriétés
            Devtm.ServiceModel.Configurations.CustomBindingsSection section = new Devtm.ServiceModel.Configurations.CustomBindingsSection();

            if (!string.IsNullOrEmpty(bindingContent))
                using (StringWriter sWriter = new StringWriter())
                {
                    StringReader sReader = new StringReader(bindingContent);
                    XmlReader reader = XmlReader.Create(sReader);
                    section.ReadXml(reader);
                }


            foreach (BindingCollectionElement item in conf.BindingCollections)

                if (item.BindingName == bindingName)
                {

                    b = Activator.CreateInstance(item.BindingType) as Binding;

                    if (!string.IsNullOrEmpty(bindingConfiguration))
                        foreach (var i2 in item.ConfiguredBindings)
                            if (i2.Name == bindingConfiguration)
                            {
                                i2.ApplyConfiguration(b);
                                break;
                            }

                    break;

                }

            return b;

        }


        public static Binding CreateBinding(string bindingName, string bindingConfiguration)
        {

            Binding b = null;

            // On récupère la section bindings
            BindingsSection conf = System.Configuration.ConfigurationManager.GetSection(@"system.serviceModel/bindings") as BindingsSection;        

            foreach (BindingCollectionElement item in conf.BindingCollections)

                if (item.BindingName == bindingName)
                {

                    b = Activator.CreateInstance(item.BindingType) as Binding;

                    if (!string.IsNullOrEmpty(bindingConfiguration))
                        foreach (var i2 in item.ConfiguredBindings)
                            if (i2.Name == bindingConfiguration)
                            {
                                i2.ApplyConfiguration(b);
                                break;
                            }

                    break;

                }

            return b;

        }



    }

}
